feat: support inheritance split and cast statements#365
feat: support inheritance split and cast statements#365hjotha wants to merge 9 commits intomendixlabs:mainfrom
Conversation
|
Follow-up pushed in This preserves explicit Validation rerun on the branch:
|
947a522 to
b1d099c
Compare
38b9eee to
e1f5d9a
Compare
|
Merge hazard note — when this PR rebases / merges with
Both cases are needed after merge. In a previous local combination the conflict was resolved in a way that left case *ast.DeclareStmt:
s.Annotations = ann
case *ast.EnumSplitStmt:
s.Annotations = ann
case *ast.InheritanceSplitStmt:
s.Annotations = ann
case *ast.CastObjectStmt:
s.Annotations = ann
...No code change requested here — just a guard-rail for the merge. |
…ations Earlier merges accidentally dropped the `s.Annotations = ann` body from the `case *ast.EnumSplitStmt:` arm. Without it every enum split built from parsed MDL lost statement-level annotations (@caption, @position, @anchor), and describe → exec → describe silently replaced user-authored captions like `'EventType?'` with the expression the split evaluates (e.g. `'\$Var/EventType'`). The fix is a one-line merge guard: restore the missing assignment. PR mendixlabs#365 has been commented with a merge-hazard note so a future rebase does not reintroduce the regression. Applies only to the combined validation branch; upstream mendixlabs#460 already has the correct body.
e1f5d9a to
ba18481
Compare
AI Code ReviewLet me review this PR based on the provided checklist. First, let me understand what the PR is about:
Now I'll go through the checklist items: Overlap & duplication
MDL syntax design (for new or modified MDL syntax)Let me check the syntax against the guidelines:
Full-stack consistency (for MDL features)Let me check if the feature is wired through the full pipeline:
Since the diff is truncated, I can't see everything, but based on what's visible:
Test coverage
Security & robustness
Scope & atomicity
Code quality
Bugs & correctnessLet me look for potential issues:
Let me check if there are other issues. In the formatAction function for CastAction: This seems correct - it handles both forms. In the inheritance split formatting: This only outputs Now, let me check the DESCRIBE roundtrip functionality more carefully. In emitInheritanceSplitStatement: This looks correct - it outputs the split type statement with cases and else branch. However, I notice a potential issue: the function assumes that Looking at cmd_microflows_show.go: This includes InheritanceSplit in the switch, so it should work. Now, let me check if there are any issues with the validation. In validate_microflow.go: This walks the bodies of cases and else, which is correct. In validate_microflow.go for bodyReturns: This requires that there is at least one case and an else body, and that the else body returns. But actually, the else body is optional according to the syntax (the proposal shows an else branch but says it's optional). Looking at the proposal: And the text: "The optional So the else branch is optional, meaning we can have: But the bodyReturns function requires an else body ( This is a bug. The validation should allow missing else body. Similarly, in LastStmtIsReturn_InheritanceSplit: Same issue - it requires an else body. Also, in the case where there is no else body, we still need to check that all cases return. Let me look at the test for this: This test only checks the case with an else body. There should be a test for the case without else body. In fact, looking at the doctype test: Automated review via OpenRouter (Nemotron Super 120B) — workflow source |
Symptom: all open PRs against main failed the shared build-and-test job in make test-integration, even when their local build/test/lint validation passed. The failures reproduced on origin/main, so they were baseline CI instability rather than PR-specific regressions. Root cause: TestWatcherDebounce could allow stale timer callbacks to send an extra message under slow scheduling, nanoflow integration fixtures used MDL syntax that no longer matched the grammar, and the doctype mx-check harness did not classify known page/nanoflow showcase consistency errors as expected limitations. Fix: guard watcher debounce callbacks with a generation counter, tighten the watcher burst test, update nanoflow fixtures to current MDL syntax, and extend the known consistency-error allowlist for showcase-only limitations. Tests: make build Tests: go test ./cmd/mxcli/tui -run TestWatcherDebounce -count=20 -v Tests: ./bin/mxcli check mdl-examples/doctype-tests/02b-nanoflow-examples.mdl Tests: go test -tags integration -count=1 -timeout 30m ./mdl/executor -run 'TestRoundtripNanoflow_(Loop|EnumParameter|Annotations)|TestMxCheck_DoctypeScripts/02b-nanoflow-examples.mdl|TestMxCheck_DoctypeScripts/03-page-examples.mdl' -v Tests: make test Tests: make lint-go Tests: make test-integration
Symptom: type-based microflow decisions and cast actions could be read from MPRs but had no first-class MDL representation, so describe/exec round-trips could not preserve InheritanceSplit and CastAction graphs. Root cause: the microflow AST, grammar, visitor, builder, describer, validator, and MPR writer only modeled boolean exclusive splits and regular actions. InheritanceCase sequence flows and CastAction BSON were not emitted back to valid project data. Fix: add split type and cast statements, parse and build inheritance branches, describe existing InheritanceSplit graphs by resolving case entity names, serialize inheritance split/case/cast BSON, and recurse through type-split bodies in validation/reference/layout code. Tests: added parser, builder, describer, terminality, validation, and MPR writer regressions plus a doctype fixture checked with mxcli check. Also ran make build, make lint-go, and make test.
Symptom: an inheritance split branch containing a nested empty-then decision could lose the boolean case value on the continuation flow when the branch joined a shared split merge. Root cause: addStructuredInheritanceSplit consumed flowBuilder.nextConnectionPoint from the nested decision but did not carry flowBuilder.nextFlowCase through branch tail wiring. Fix: preserve the pending case value on inheritance branch tails and reapply it when connecting to the next statement, parent continuation, or shared merge. Tests: add a builder regression for nested empty-then inheritance branches that must keep CaseValue=true on continuation flows.
Symptom: type split cases with equivalent empty/fall-through bodies could be reordered after describe/exec/describe. Root cause: inheritance split case flows did not carry a stable ordering signal when multiple cases shared the same split-to-merge shape, so the describer could only rely on connection metadata that was identical across those branches. Fix: encode the parsed case order into valid split flow connection pairs and sort inheritance split flows by that encoded order during describe. Tests: added traversal coverage for shuffled stored inheritance case flows that must still describe in the original authoring order; existing inheritance split builder and cast coverage continues to pass.
Symptom: inheritance split roundtrips could lose branch flow anchors or collapse an explicit empty ELSE branch into an untyped flow. Root cause: inheritance branch building did not thread statement anchor metadata through split-to-body and body-to-merge flows, and empty ELSE tails used a plain sequence flow instead of an explicit inheritance case. Fix: propagate authored branch anchors across inheritance branch body flows and keep empty ELSE branches represented by an explicit empty InheritanceCase. Tests: added builder coverage for anchored inheritance branch bodies and tightened the existing case-flow assertion to select the intended typed branch.
Symptom: describing a microflow with an inheritance split inside an if could emit the parent continuation inside the matching split case. Re-executing that MDL made variables declared in the continuation branch-scoped, so Mendix mx check reported invalid or missing return/variable state. Root cause: nested inheritance split emission stopped branches only at the split's own merge. When the inheritance split had no merge because one branch returned and the other fell through to the parent if merge, branch traversal used an empty stop ID and consumed the parent tail. Fix: when emitting an inheritance split, prefer the split's own merge but fall back to the caller's stop ID. This keeps parent continuation statements outside the split cases while preserving standalone inheritance split behavior. Tests: added a synthetic nested if/split-type traversal regression that verifies the parent tail is emitted after both end split and end if.
ba18481 to
64db8f7
Compare
AI Code ReviewReview SummaryThis PR adds first-class MDL support for type-based microflow decisions ( Critical IssuesNone found. Moderate IssuesNone found. Minor Issues
What Looks Good
RecommendationApprove the PR. The implementation is complete, follows all MDL design guidelines, has full test coverage, and maintains proper architectural boundaries. The minor documentation clarification does not block approval. Automated review via OpenRouter (Nemotron Super 120B) — workflow source |
|
CI stabilization note: merged #412 into this branch so it uses the same integration-CI baseline as the rest of the active PR set. |
Symptom: CI failed in TestMxCheck_DoctypeScripts/empty_java_action_argument.mdl because a Java action declared as RETURNS Void was written as an entity return type named .void, and Studio Pro reported CE1613. Root cause: the generic data-type visitor treats bare qualified names as entity/enumeration references. Java action return types reused that generic path, so the explicit Void spelling became a qualified name instead of ast.TypeVoid. Fix: add a Java-action return-type wrapper that maps unqualified Void to ast.TypeVoid while leaving generic data-type parsing unchanged for parameters and attributes. Tests: added visitor coverage for explicit RETURNS Void; verified mxcli check for the doctype fixture and the targeted integration subtest that failed in GitHub Actions.
AI Code ReviewCritical IssuesNone found. Moderate IssuesPotential missing visitor implementation: The PR description states that the visitor was extended to parse LSP integration not explicitly verified: While the DESCRIBE roundtrip appears implemented, there are no visible updates to LSP wiring ( Minor IssuesTruncated nanoflow example: The diff shows significant truncation of What Looks Good
RecommendationApprove with verification needed The PR demonstrates strong implementation of the inheritance split and cast statements feature with proper attention to the full MDL pipeline where visible. The syntax design is correct and follows established patterns. Before final approval, please verify:
All visible aspects of the implementation meet the project's standards for code quality, test coverage, and architectural consistency. The feature enables complete round-trip support for inheritance splits and casts as requested in the original issue. Automated review via OpenRouter (Nemotron Super 120B) — workflow source |
Summary
Adds first-class MDL support for type-based microflow decisions and cast actions:
Root Cause
The SDK layer could parse
InheritanceSplitandCastActionobjects from MPRs, but MDL had no AST or grammar nodes for them. The writer also did not serialize inheritance split/case/cast data back to valid microflow BSON, so describe/exec round-trips could not preserve these graphs.Fix
InheritanceSplitStmt,InheritanceSplitCase, andCastObjectStmtto the microflow AST.split typebranches andcastactions.InheritanceSplitgraphs withInheritanceCasesequence flows.Validation
go test ./mdl/visitor -run 'TestMicroflowParsing_(Inheritance|Cast)' -count=1go test ./mdl/executor -run 'Test(FormatActivity_InheritanceSplit|FormatAction_CastAction|Builder_InheritanceSplit|TraverseFlow_InheritanceSplit|LastStmtIsReturn_InheritanceSplit|ValidateMicroflow_InheritanceSplit)' -count=1go test ./sdk/mpr -run 'Test(BuildSequenceFlowCase_InheritanceCase|SerializeMicroflowObject_InheritanceSplit|CastAction_RoundtripVariableName)' -count=1./bin/mxcli check mdl-examples/doctype-tests/inheritance_split_statement.test.mdlmake buildmake lint-gomake testCloses #348
Part of #332